﻿using System;
using System.Collections.Generic;

namespace BizElements.BusinessLayer
{
    /// <summary>Dummy implementation of <see cref="IAppSettingsManager"/> interface for use in applications that 
    /// don't require app-settings or use DBMS for which app-settings is not developed, yet.</summary>
    /// <remarks><para>By default, SettingsUtil uses <see cref="BizElements.BusinessLayer.AppSettingsManager"/> to manage settings in database.
    /// This can be overrided in <b>appSettings</b> section of Web.config file. Example:
    /// <code>
    /// &lt;add key="BizElements.BusinessLayer.SettingsUtil.ManagerAssembly" value="BizElements.BusinessLayer"/&gt;
    /// &lt;add key="BizElements.BusinessLayer.SettingsUtil.ManagerClass" value="BizElements.BusinessLayer.NullAppSettingsManager"/&gt;</code>
    /// </para>
    /// </remarks>
    [Serializable]
    public sealed class NullAppSettingsManager : IAppSettingsManager
    {
        #region IAppSettingsManager.

        /// <summary>Returns empty list.</summary>
        /// <param name="filter">Ignored.</param>
        /// <returns>Empty list.</returns>
        public IList<IAppSetting> Find(IAppSetting filter)
        {
            return new List<IAppSetting>();
        }

        /// <summary>Returns empty list.</summary>
        /// <param name="filter">Ignored.</param>
        /// <param name="options">Ingored.</param>
        /// <returns>Empty list.</returns>
        public IList<IAppSetting> Find(IAppSetting filter, AppSettingsFilterOptions options)
        {
            return new List<IAppSetting>();
        }

        /// <summary>Does nothing.</summary>
        /// <param name="filter">Ignored.</param>
        public void Delete(IAppSetting filter)
        {
        }

        /// <summary>Does nothing.</summary>
        /// <param name="setting">Ignored.</param>
        public void Save(IAppSetting setting)
        {
        }

        /// <summary>Creates a new empty <see cref="IAppSetting"/> object.</summary>
        /// <returns><see cref="IAppSetting"/> object.</returns>
        public IAppSetting NewSetting()
        {
            return new AppSettingDto();
        }

        #endregion
    }

    /// <summary>Contains app-setting data.</summary>
    internal class AppSettingDto : IAppSetting
    {
        #region IAppSetting.

        /// <summary>
        /// Gets or sets the value, typically an integer or a string, which identifies the actor/user to which 
        /// the current setting applies. If <b>null</b> then the setting is global.
        /// </summary>
        /// <value>ID if the setting is user-defined, <b>null</b> if it is global.</value>
        public object ActorId { get; set; }

        /// <summary>
        /// Gets or sets the value which identifies the application instance.
        /// </summary>
        /// <value>A string that identifies an application instance. <see cref="String.Empty"/> and <b>null</b> do not represent a valid value.</value>
        /// <remarks>Assign a unique name to each instance of the same or different applications. This is
        /// especially important if there is a chance that multiple instances will share the same settings 
        /// storage (ie. the same database).</remarks>
        public string Application { get; set; }

        /// <summary>
        /// Gets or sets the value which indentifies the module (eg. form, class name) of the application 
        /// that contains the component to which the setting is applied.
        /// </summary>
        /// <value>A string that identifies an application module. <see cref="String.Empty"/> and <b>null</b> do not represent a valid value.</value>
        /// <remarks>Use fully qualified class names to uniquely identify a module in an object-oriented application. 
        /// Use some similar naming conventions for non-OO modules such as stored procedures, reports etc.</remarks>
        public string Module { get; set; }

        /// <summary>
        /// Gets or sets the context/condition which defines whether the setting may be applied to the <see cref="Component"/>.
        /// </summary>
        public string Context { get; set; }

        /// <summary>
        /// Gets or sets the name of the component, typically a controll or a class member, contained in the <see cref="Module"/>.
        /// </summary>
        /// <value>A string that identifies an component. <see cref="String.Empty"/> and <b>null</b> do not represent a valid value.</value>
        /// <remarks>Use member name to uniquely identify a modulte component (class member) in an object-oriented
        /// application. Use some similar naming convention for non-OO modules such as parameter names for
        /// stored procedures, reports etc.</remarks>
        public string Component { get; set; }

        /// <summary>
        /// Gets or sets the optional path which defines the property of the component which is to receive the <see cref="Value"/>.
        /// </summary>
        /// <value>Slash-delimmited properties. The last property in the sequencs is the one which receives the value.
        /// <see cref="String.Empty"/> or <b>null</b> if the value is assigned directly to the component.</value>
        /// <remarks><para>Syntax is designed to mimic URI, XPATH and file path syntax. Elements, ie. properties 
        /// and indexes, of the path are separated by "/" characters.</para></remarks>
        public string PropertyPathString { get; set; }

        /// <summary>
        /// Gets or sets the elements, ie. properties and indexes, of the <see cref="PropertyPathString"/>.
        /// </summary>
        /// <value>Array of strings. Empty array if the value is assigned directly to the component.
        /// <b>null</b> does not represent a valid value.</value>
        public string[] PropertyPath { get; set; }

        /// <summary>
        /// Gets or sets the value of the property defined by the <see cref="PropertyPathString"/>.
        /// </summary>
        /// <value>A value compatibile with the property/parameter which is to receive it.</value>
        public object Value { get; set; }

        #endregion
    }
}
